package com.sinosoft.sm.user.service;


import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sinosoft.sm.system.common.SystemContants;
import com.sinosoft.sm.system.common.entity.PaginationEntity;
import com.sinosoft.sm.system.common.exception.ObjectIsExistedException;
import com.sinosoft.sm.system.common.exception.ObjectIsNotExistedException;
import com.sinosoft.sm.system.common.utils.DigestUtil;
import com.sinosoft.sm.system.common.utils.EncodeUtil;
import com.sinosoft.sm.system.common.utils.StringUtil;
import com.sinosoft.sm.system.role.entity.UserRoleRefEntity;
import com.sinosoft.sm.system.role.manager.api.RoleManager;
import com.sinosoft.sm.system.security.SecurityUtil;
import com.sinosoft.sm.user.entity.UserEntity;
import com.sinosoft.sm.user.manager.api.UserManager;
import com.sinosoft.sm.user.service.api.UserService;

/**
 * 用户信息服务类
 * @author leichao
 */
public class UserServiceImpl implements UserService {
	
	public static final String HASH_ALGORITHM = "SHA-1";	//	加密算法
	public static final int HASH_INTERATIONS = 1024;	//	随机盐生成函数中，遍历大小值
	private static final int SALT_SIZE = 8;	//	盐长度


	private UserManager userManager;
	
	private RoleManager roleManager;
	
	public void setRoleManager(RoleManager roleManager) {
		this.roleManager = roleManager;
	}

	private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

	public void setUserManager(UserManager userManager) {
		this.userManager = userManager;
	}

	/**
	 * 根据用户名获取用户信息
	 * @param username 用户名
	 * @return 用户信息
	 * @throws ObjectIsNotExistedException 
	 */
	public UserEntity getUserByUsername(String username) throws ObjectIsNotExistedException{
		if(StringUtil.isBlank(username)){
			return null;
		}
		UserEntity user = userManager.getUserByUsername(username);
		if(user == null){
			throw new ObjectIsNotExistedException("用户不存在");
		}
		return user;
	}
	
	/**
	 * 校验用户密码
	 * 传入的密码为原文
	 * 若username或password为空，抛出异常消息“UserServiceImpl:checkUserPassword调用失败，username或password为空”
	 */
	public boolean checkUserPassword(String username, String password)
			throws ObjectIsNotExistedException {
		if(StringUtil.isBlank(username) || StringUtil.isBlank(password)) {
			logger.error(("UserServiceImpl:checkUserPassword调用失败，参数为空"));
			return false;
		}
		return comparePassword(password, userManager.getUserByUsername(username));
	}
	
	/**
	 * 更新用户密码
	 * 新密码需要加密后存储
	 * 若参数为空，则抛出异常消息“UserServiceImpl:updateUserPassword调用失败，参数为空”
	 * 若用户信息不存在，则抛出异常消息“UserServiceImpl:updateUserPassword调用失败，用户信息不存在”
	 */
	public boolean updateUserPassword(String username, String password)
			throws ObjectIsNotExistedException {
		if(StringUtil.isBlank(username) || StringUtil.isBlank(password)) {
			logger.error(("UserServiceImpl:updateUserPassword调用失败，参数为空"));
			return false;
		}
		UserEntity userEntity = userManager.getUserByUsername(username);
		if(userEntity == null) {
			throw new ObjectIsNotExistedException("UserServiceImpl:updateUserPassword调用失败，用户信息不存在");
		}else {
			userEntity.setPassword(password);
			entryptPassword(userEntity);
			userManager.updateUserPassword(username, userEntity.getPassword());
		}
		return true;
	}
	
	/**
	 *更新用户状态
	 * @throws ObjectIsNotExistedException 
	 */
	public boolean updateUserState(String username, String state) throws ObjectIsNotExistedException {
		if(StringUtil.isBlank(state)){
			return false;
		}
		switch(state){
			case "1" :
				state = SystemContants.USER_STATE_ON;
				break;
			case "0":
				state = SystemContants.USER_STATE_OFF;
				break;
			default:
				return false;
		}
		UserEntity userEntity = userManager.getUserByUsername(username);
		if(userEntity == null) {
			throw new ObjectIsNotExistedException("UserServiceImpl:updateUserPassword调用失败，用户信息不存在");
		}else {
			userManager.updateUserState(username,state);
		}
		return true;
	}
	
	/**
	 *	根据条件获取用户信息
	 *	若条件为空则查询所有用户信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public PaginationEntity getUsers(UserEntity entity, int page, int rows) {
		PageHelper.startPage(page, rows);
		List<UserEntity> users = userManager.getUsers(entity);
		PageInfo pageInfo = new PageInfo(users);
		return new PaginationEntity((int)pageInfo.getTotal(), pageInfo.getPageNum(), users);
	}

	/**
	 * 添加用户信息。
	 * 默认绑定普通用户角色
	 * @throws ObjectIsExistedException 
	 */
	@Override
	public boolean addUser(UserEntity userEntity) throws ObjectIsExistedException {
		if(userEntity == null) {
			logger.error("UserServiceImpl:addUser调用失败，userEntity为空");
			return false;
		}
		String username = userEntity.getUsername();
		if(userManager.getUserByUsername(username) != null){
			logger.error("UserServiceImpl:addUser调用失败，用户名已存在");
			throw new ObjectIsExistedException("用户名已存在");
		}
		entryptPassword(userEntity);	//	密码加密
		userEntity.setCreater(SecurityUtil.getUsername());
		userEntity.setCreatetime(new Date());
		userEntity.setState(SystemContants.USER_STATE_ON);
		userManager.addUser(userEntity);
		//绑定用户角色（普通用户）
		UserRoleRefEntity roleRef = new UserRoleRefEntity();
		roleRef.setUsername(username);
		roleRef.setRoleid(SystemContants.USER_ROLE_PUBLIC);
		roleManager.addRoleRef(roleRef);
		return true;
	}
	
	/**
	 * 密码比较
	 * 比较传入的密码原文与用户信息中加密后的密码是否匹配
	 * @param password	需要比较的密码
	 * @param userEntiy	用户信息
	 * @return	true/false
	 */
	private boolean comparePassword(String password, UserEntity userEntiy) {
		if(userEntiy == null) {
			return false;
		}
		byte[] salt = EncodeUtil.decodeHex(userEntiy.getSalt());
		byte[] hashPassword = DigestUtil.sha1(password.getBytes(), salt, HASH_INTERATIONS);
		if(userEntiy.getPassword().equals(EncodeUtil.encodeHex(hashPassword))){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 密码加密
	 * 若盐不存在则生成随机的盐，并经过1024次 SHA1哈希。若盐存在则直接解码
	 * @param userEntity	用户信息
	 */
	private void entryptPassword(UserEntity userEntity) {
		byte[] salt = null;
		if(!StringUtil.isBlank(userEntity.getSalt())) {
			salt = EncodeUtil.decodeHex(userEntity.getSalt());
		} else {
			salt = DigestUtil.generateSalt(SALT_SIZE);
			userEntity.setSalt(EncodeUtil.encodeHex(salt));
		}
		byte[] hashPassword = DigestUtil.sha1(userEntity.getPassword().getBytes(), salt, HASH_INTERATIONS);
		userEntity.setPassword(EncodeUtil.encodeHex(hashPassword));
	}

	
}
